package com.lcz.manage.util;

import com.google.common.base.Objects;
import com.lcz.manage.util.exception.CCException;

import java.text.ParseException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

public class DateUtils {

    public static final String DATE_FORMAT_1 = "yyyy-MM-dd";
    public static final String DATE_FORMAT_2 = "yyyyMMdd";
    public static final String DATE_FORMAT_4 = "yyyyMM";
    public static final String DATE_FORMAT_5 = "yyyy";
    public static final String DATETIME_FORMAT_1 = "yyyy-MM-dd HH:mm:ss";
    public static final String DATETIME_FORMAT_3 = "yyyy-MM-dd HH-mm-ss";
    public static final String DATETIME_FORMAT_2 = "yyyyMMddHHmmss";
    public static final String DATETIME_FORMAT_4 = "yyyy/MM/dd HH:mm:ss";
    public static final String DATETIME_FORMAT_5 = "yyyy-MM-dd HH:mm:ss.SSS";
    public static final String DATETIME_FORMAT_6 = "yyyy-MM-dd HH:mm:ss";
    public static final String DATE_FORMAT_3 = "yyyy年MM月dd日";
    public static final String TIME_FORMAT_1 = "HHmmss";
    public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
    public static final String DEFAULT_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
    public static final String NAME_FILE_DATE_FORMAT = "yyyyMMdd_HHmmss";
    private static final Integer DATE_TIME_LENGTH_11 = 11;
    private static final Integer DATE_LENGTH_8 = 8;

    private DateUtils() {
    }

    public static SimpleDateFormat getDateFormat(String format) {
        return new SimpleDateFormat(format);
    }

    public static String date2String(Date date, String format) {
        if (date == null) {
            return "";
        } else {
            SimpleDateFormat sdf = getDateFormat(format);
            return sdf.format(date);
        }
    }

    public static String date2String(Date date) {
        return date2String(date, "yyyy-MM-dd");
    }

    public static String getCurrentDate() {
        Date date = new Date();
        return date2String(date, "yyyy-MM-dd");
    }

    public static String getNameFileCurrentDate() {
        Date date = new Date();
        return date2String(date, "yyyyMMdd_HHmmss");
    }

    public static Date string2Date(String date) {
        if (StringUtils.isEmpty(date)) {
            return null;
        } else {
            Date ret;
            if (date.length() > DATE_TIME_LENGTH_11) {
                if (date.contains("-")) {
                    if (date.contains(":")) {
                        ret = string2Date(date, "yyyy-MM-dd HH:mm:ss");
                    } else {
                        ret = string2Date(date, "yyyy-MM-dd HH-mm-ss");
                    }
                } else if (date.contains("/")) {
                    ret = string2Date(date, "yyyy/MM/dd HH:mm:ss");
                } else {
                    ret = string2Date(date, "yyyyMMddHHmmss");
                }
            } else if (date.contains("-")) {
                ret = string2Date(date, "yyyy-MM-dd");
            } else if (date.length() == DATE_LENGTH_8) {
                ret = string2Date(date, "yyyyMMdd");
            } else {
                ret = string2Date(date, "yyyy年MM月dd日");
            }

            return ret;
        }
    }

    public static Date string2Date(String date, String format) {
        if (StringUtils.isEmpty(format)) {
            throw new IllegalArgumentException("the date format string is null!");
        } else {
            SimpleDateFormat sdf = getDateFormat(format);

            try {
                return sdf.parse(date);
            } catch (ParseException var4) {
                throw new IllegalArgumentException("the date string " + date + " is not matching format: " + format, var4);
            }
        }
    }

    public static String getStandardNowTime() {
        SimpleDateFormat sdf = getDateFormat("yyyy-MM-dd HH:mm:ss");
        return sdf.format(new Date());
    }

    public static String getNowDate(String format) {
        Date date = new Date();
        SimpleDateFormat df = new SimpleDateFormat(format);
        return df.format(date);
    }

    public static Date offsetSecond(Date date, long seconds) {
        if (date == null) {
            return null;
        } else {
            long time = date.getTime();
            long time2 = time + seconds * 1000L;
            long time3 = time + seconds * 1000L - 3600000L;
            Date date2 = new Date(time2);
            Date date3 = new Date(time3);
            Calendar calendarDate = Calendar.getInstance();
            calendarDate.setTime(date);
            Calendar calendarDate2 = Calendar.getInstance();
            calendarDate2.setTime(date2);
            Calendar calendarDate3 = Calendar.getInstance();
            calendarDate3.setTime(date3);
            long dstDate = (long)calendarDate.get(16);
            long dstDate2 = (long)calendarDate2.get(16);
            long dstDate3 = (long)calendarDate3.get(16);
            long dstOffset = dstDate - dstDate2;
            boolean isNeedReset = dstOffset == 0L || dstDate2 - dstDate3 != 0L && dstDate2 != 0L;
            return !isNeedReset ? date2 : new Date(time2 + dstOffset);
        }
    }

    public static Date offsetMinute(Date date, long minutes) {
        return offsetSecond(date, 60L * minutes);
    }

    public static Date addDateMinut(Date day, int x) {
        return offsetMinute(day, (long)x);
    }

    public static String reduceDateMinut(Date day, int x) {
        Date date = addDateMinut(day, -x);
        return getDate(date, "yyyy-MM-dd HH:mm:ss");
    }

    public static Date offsetHour(Date date, long hours) {
        return offsetMinute(date, 60L * hours);
    }

    public static Date offsetDay(Date date, int days) {
        return offsetHour(date, 24L * (long)days);
    }

    public static Date dateAddDay(Date now, int day) {
        return offsetDay(now, day);
    }

    public static Date addDate(Date date, long day) {
        return dateAddDay(date, (int)day);
    }

    public static Date deleteDate(Date date, long day) {
        return dateAddDay(date, -((int)day));
    }

    public static Date offsetWeek(Date date, int weeks) {
        return offsetDay(date, 7 * weeks);
    }

    public static Date offsetMonth(Date date, int months) {
        if (date == null) {
            return null;
        } else {
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(date);
            int curDay = calendar.get(5);
            int maxDay = calendar.getActualMaximum(5);
            calendar.set(5, 1);
            calendar.add(2, months);
            int newMaxDay = calendar.getActualMaximum(5);
            if (curDay == maxDay) {
                calendar.set(5, newMaxDay);
            } else if (curDay > newMaxDay) {
                calendar.set(5, newMaxDay);
            } else {
                calendar.set(5, curDay);
            }

            return new Date(calendar.getTimeInMillis());
        }
    }

    public static Date dateAddMonth(Date now, int month) {
        return offsetMonth(now, month);
    }

    public static Date dateReduceMonth(Date now, int month) {
        return offsetMonth(now, -month);
    }

    public static Date dateReduceDay(Date now, int day) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(now);
        calendar.add(5, -day);
        return calendar.getTime();
    }

    public static Date offsetYear(Date date, int years) {
        if (date == null) {
            return null;
        } else {
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(date);
            calendar.add(1, years);
            return new Date(calendar.getTimeInMillis());
        }
    }

    public static Date dateAddYear(Date now, int year) {
        return offsetYear(now, year);
    }

    public static long differDateInDays(Date beginDate, Date endDate, DateUtils.TimeType timeType) {
        long begin = beginDate.getTime();
        long end = endDate.getTime();
        long surplus = end - begin;
        Calendar calendarBeginDate = Calendar.getInstance();
        calendarBeginDate.setTime(beginDate);
        Calendar calendarEndDate = Calendar.getInstance();
        calendarEndDate.setTime(endDate);
        int dstOffset = calendarBeginDate.get(16) - calendarEndDate.get(16);
        surplus += (long)dstOffset;
        long ret = 0L;
        switch(timeType) {
            case SECOND:
                ret = surplus / 1000L;
                break;
            case MINUTE:
                ret = surplus / 1000L / 60L;
                break;
            case HOUR:
                ret = surplus / 1000L / 60L / 60L;
                break;
            case DAY:
                ret = surplus / 1000L / 60L / 60L / 24L;
        }

        return ret;
    }

    public static int getBetweenDays(Date before, Date after) {
        return (int)differDateInDays(before, after, DateUtils.TimeType.DAY);
    }

    public static boolean isInRange(String date, String beginDate, String endDate) {
        int dateLen = date.length();
        int beginDateLen = beginDate.length();
        int endDateLen = endDate.length();
        if (Objects.equal(beginDateLen, dateLen) && Objects.equal(dateLen, endDateLen)) {
            boolean asc = isAsc(beginDate, endDate);
            if (asc) {
                return date.compareTo(beginDate) >= 0 && date.compareTo(endDate) <= 0;
            } else {
                return date.compareTo(beginDate) >= 0 || date.compareTo(endDate) <= 0;
            }
        } else {
            throw new CCException("[" + date + "], [" + beginDate + "]和[" + endDate + "]的长度不一致");
        }
    }

    public static boolean isInRange(Date date, Date beginDate, Date endDate) {
        long time = date.getTime();
        long beginTime = beginDate.getTime();
        long endTime = endDate.getTime();
        return time >= beginTime && time <= endTime;
    }

    public static int compare(Date beginDate, Date endDate) {
        long beginTime = beginDate.getTime();
        long endTime = endDate.getTime();
        return Long.compare(beginTime, endTime);
    }

    private static boolean isAsc(String beginDateStr, String endDateStr) {
        return beginDateStr.compareTo(endDateStr) < 0;
    }

    public static Date dateOffsetCalc(int offset, String dateTimeStr, int intOut) {
        Date ret = string2Date(dateTimeStr);
        boolean hasTimeStr = dateTimeStr.length() > 11;
        if (ret != null) {
            Calendar cal = Calendar.getInstance();
            cal.setTime(ret);
            if (intOut == 0) {
                if (hasTimeStr) {
                    cal.add(13, offset);
                } else {
                    cal.add(5, offset);
                }
            } else if (hasTimeStr) {
                cal.add(13, -1 * offset);
            } else {
                cal.add(5, -1 * offset);
            }

            ret = cal.getTime();
        }

        return ret;
    }

    public static Date getNowDate() {
        return new Date();
    }

    public static Date getStartTimeOfDay(Date dt) {
        if (dt == null) {
            return null;
        } else {
            Calendar cal = Calendar.getInstance();
            cal.setTime(dt);
            cal.set(11, 0);
            cal.set(12, 0);
            cal.set(13, 0);
            cal.set(14, 0);
            return cal.getTime();
        }
    }

    public static String getDayBeginStr(Date date) {
        Date startTimeOfDay = getStartTimeOfDay(date);
        return getDate(startTimeOfDay, "yyyy-MM-dd HH:mm:ss");
    }

    public static Date getDayBegin(Date date) {
        return getStartTimeOfDay(date);
    }

    public static Date getEndTimeOfDay(Date dt) {
        if (dt == null) {
            return null;
        } else {
            Calendar cal = Calendar.getInstance();
            cal.setTime(dt);
            cal.set(11, 23);
            cal.set(12, 59);
            cal.set(13, 59);
            cal.set(14, 999);
            return cal.getTime();
        }
    }

    public static String getDayEndStr(Date date) {
        Date endTimeOfDay = getEndTimeOfDay(date);
        return getDate(endTimeOfDay, "yyyy-MM-dd HH:mm:ss");
    }

    public static Date getDayEnd(Date date) {
        return getEndTimeOfDay(date);
    }

    public static Date parseDate(String source, String pattern) {
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        return sdf.parse(source, new ParsePosition(0));
    }

    public static Date getDate(Integer year, Integer month, Integer day) {
        Calendar calendar = Calendar.getInstance();
        calendar.set(year, month - 1, day);
        return calendar.getTime();
    }

    public static String getDate() {
        return getDate(new Date());
    }

    public static String getDate(Date date, String format) {
        if (null == date) {
            return "";
        } else {
            SimpleDateFormat formatter = new SimpleDateFormat(format);
            return formatter.format(date);
        }
    }

    public static String getDate(Date date) {
        return getDate(date, "yyyy-MM-dd");
    }

    public static Date getDate(String dateStr) {
        if (StringUtils.isEmpty(dateStr)) {
            return null;
        } else if (isDate(dateStr)) {
            return getDate(dateStr, "yyyyMMdd");
        } else {
            return isDateTime(dateStr) ? getDate(dateStr, "yyyy-MM-dd HH:mm:ss.SSS") : null;
        }
    }

    public static boolean isDate(String str) {
        return isDateTime(str, "yyyyMMdd");
    }

    public static Date getDate(String dateStr, String pattern) {
        if (isDateTime(dateStr, pattern)) {
            SimpleDateFormat df = new SimpleDateFormat(pattern);

            try {
                return df.parse(dateStr);
            } catch (Exception var4) {
                return null;
            }
        } else {
            return null;
        }
    }

    public static boolean isDateTime(String str) {
        return isDateTime(str, "yyyy-MM-dd HH:mm:ss.SSS");
    }

    public static boolean isDateTime(String str, String pattern) {
        if (StringUtils.isEmpty(str)) {
            return false;
        } else {
            boolean convertSuccess = true;
            SimpleDateFormat format = new SimpleDateFormat(pattern);

            try {
                format.setLenient(false);
                format.parse(str);
            } catch (Exception var5) {
                convertSuccess = false;
            }

            return convertSuccess;
        }
    }

    public static String getTimeStr6(Date date) {
        return getDate(date, "HHmmss");
    }

    public static String getTimeStr6() {
        return getDate(new Date(), "HHmmss");
    }

    public static Date getBeginDayOfMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(5, 1);
        calendar.set(11, 0);
        calendar.set(12, 0);
        calendar.set(13, 0);
        calendar.set(14, 0);
        return new Date(calendar.getTimeInMillis());
    }

    public static Date getBeginDayOfYear(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(6, 1);
        calendar.set(11, 0);
        calendar.set(12, 0);
        calendar.set(13, 0);
        calendar.set(14, 0);
        return new Date(calendar.getTimeInMillis());
    }

    public static Date getEndDateTime(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(11, 23);
        cal.set(12, 59);
        cal.set(13, 59);
        cal.set(14, 0);
        return cal.getTime();
    }

    public static Date getThisMonthFirstDay() {
        return getBeginDayOfMonth(new Date());
    }

    public static Date getLastDayOfMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int maxDay = calendar.getActualMaximum(5);
        calendar.set(5, maxDay);
        calendar.set(11, 23);
        calendar.set(12, 59);
        calendar.set(13, 59);
        date.setTime(calendar.getTimeInMillis());
        return date;
    }

    public static Date getThisMonthLastDay() {
        return getLastDayOfMonth(new Date());
    }

    public static Date getThisWeekFirstDay() {
        Calendar calendar = Calendar.getInstance();
        int dayOfWeek = calendar.get(7);
        calendar.add(7, -(dayOfWeek - 1));
        calendar.set(11, 0);
        calendar.set(12, 0);
        calendar.set(13, 0);
        calendar.set(14, 0);
        return new Date(calendar.getTimeInMillis());
    }

    public static boolean isSame(Date d1, Date d2) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
        return dateFormat.format(d1).equals(dateFormat.format(d2));
    }

    public static String getNowDay() {
        SimpleDateFormat formatter = new SimpleDateFormat("dd");
        return formatter.format(new Date());
    }

    public static String getCurrentDateStr() {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
        return formatter.format(new Date());
    }

    public static Date getStartTimeOfNextDay(Date dt) {
        if (dt == null) {
            return null;
        } else {
            Calendar cal = Calendar.getInstance();
            cal.setTime(dt);
            cal.set(11, 0);
            cal.set(12, 0);
            cal.set(13, 0);
            cal.set(14, 0);
            cal.add(5, 1);
            return cal.getTime();
        }
    }

    public static String getHyphenDate() {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
        return formatter.format(new Date());
    }

    public static String getHyphenDate(Date date) {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
        return formatter.format(date);
    }

    public static int calWeekNumber(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setFirstDayOfWeek(2);
        calendar.setTime(date);
        return calendar.get(3);
    }

    public int getLastDayOfMonthByDate(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.getActualMaximum(5);
    }

    public static Date getDateTime(Date date, String time) {
        if (StringUtils.isEmpty(time)) {
            return date;
        } else {
            String[] split = time.split(":");
            if (split.length < 3) {
                return date;
            } else {
                Calendar cal = Calendar.getInstance();
                cal.setTime(date);
                cal.set(11, Integer.valueOf(split[0]));
                cal.set(12, Integer.valueOf(split[1]));
                cal.set(13, Integer.valueOf(split[2]));
                cal.set(14, 0);
                return cal.getTime();
            }
        }
    }

    public static enum TimeType {
        SECOND(0),
        MINUTE(1),
        HOUR(2),
        DAY(3);

        private int code;

        private TimeType(int code) {
            this.code = code;
        }

        public int getCode() {
            return this.code;
        }
    }
}
